查看原文
其他

2020网鼎杯青龙组_re_signal

Craft_A 看雪学院 2021-03-06

本文为看雪论坛优秀文章

看雪论坛作者ID:Craft_A






2020 网鼎杯青龙组_re_signal


直接 IDA 分析,将表 0x403040 拷贝到 opcode_table 中拷贝了 456 个字节,将 opcode_table 传入 vm_operad 中,并传入一个 114 ,可以发现 456 是 114 的 4 倍,因此 114 就是 opcode 以 int 大小索引的长度。
  
 
opcode表:[10,4,16,8,3,5,1,4,32,8,5,3,1,3,2,8,11,1,12,8,4,4,1,5,3,8,3,33,1,11,8,11,1,4,9,8,3,32,1,2,81,8,4,36,1,12,8,11,1,5,2,8,2,37,1,2,54,8,4,65,1,2,32,8,5,1,1,5,3,8,2,37,1,4,9,8,3,32,1,2,65,8,12,1,7,34,7,63,7,52,7,50,7,114,7,51,7,24,7,167,7,49,7,241,7,40,7,132,7,193,7,30,7,122]
 
进入 vm_operad 分析,可以发现从 op 表中取值进行不同的操作
 
 
这里有几个 case 还是比较好分析的,case 10 进入 read 函数跟进后发现就是输入,且输入的长度必须是 15 个,最终的值是放在 v3 中,可以确定 v3 数组就是保存就是 input。
 
 
 
case 7 也比较好分析,即使判断 v4 [v8] 与 opcode 中的值进行判断,如果不满足则失败,这里通过对 v8 这个索引进行搜索,发现就这里一处带引用了,因此 v4 从一开始便要与 opcode 中的相等。
 
 
下面打印出 opcode 表,这里可以明显的看到从 7 开始的地方后面就是与 v4比对的值,并且刚好 15 个。

opcode表:[10,4,16,8,3,5,1,4,32,8,5,3,1,3,2,8,11,1,12,8,4,4,1,5,3,8,3,33,1,11,8,11,1,4,9,8,3,32,1,2,81,8,4,36,1,12,8,11,1,5,2,8,2,37,1,2,54,8,4,65,1,2,32,8,5,1,1,5,3,8,2,37,1,4,9,8,3,32,1,2,65,8,12,1,7,34,7,63,7,52,7,50,7,114,7,51,7,24,7,167,7,49,7,241,7,40,7,132,7,193,7,30,7,122]

有些操作数后面跟的数据而非运算数值

v4 需要满足:[34,63,52,50,114,51,24,167,49,241,40,132,193,30,122]
 
下面就有几个问题要分析:
1. v4如何产生的?
2. v3如何参与计算的?

通过分析 case 1 可以发现 v4 [v7]=v5,v4 的产生是由 v5 赋值而来, v7 初始化为 0 ,其他并无赋值,由此可知,case1 控着这 v4 从开始的生成,可以从 op 表中发现 1 就是有 15 个,该 case 中的 v9 , v5 则可以判断处分别为:input 的运算取值索引, v5 运算结果。
 
 
接下来就要还原 v3 的计算流程的,根据 opcode 分析,这里可以知道 case 2,3,4,5都是进行的 op_code_table_index + 1 取值 op_code_table_index += 2 迭代,因此这几个操作数后面跟的一定是运算的数值并非操作数。
 


通过分析可以根据比较,写出脚本自动还原,(逆过程+逆运算)


public class Main { public static void main(String[] args) { char re[] = {34,63,52,50,114,51,24,167,49,241,40,132,193,30,122}; // int opcode[] = { //原始code // 4,16,8,3,5,1, // 4,32,8,5,3,1, // 3,2,8,11,1, // 12,8,4,4,1, // 5,3,8,3,33,1, // 11,8,11,1, // 4,9,8,3,32,1, // 2,81,8,4,36,1, // 12,8,11,1, // 5,2,8,2,37,1, // 2,54,8,4,65,1, // 2,32,8,5,1,1, // 5,3,8,2,37,1, // 4,9,8,3,32,1, // 2,65,8,12,1 // }; int opcode[] = { //调整code顺序 3,5,8,4,16,1, 5,3,8,4,32,1, 11,8,3,2,1, 4,4,8,12,1, 3,33,8,5,3,1, 11,8,11,1, 3,32,8,4,9,1, 4,36,8,2,81,1, 11,8,12,1, 2,37,8,5,2,1, 4,65,8,2,54,1, 5,1,8,2,32,1, 2,37,8,5,3,1, 3,32,8,4,9,1, 12,8,2,65,1 }; char tmp = 0; int tmp_index = 0; int opcode_index = 0; int re_index = 0; char flag[] = new char[15]; int flag_index = 0; while(opcode_index < 83){
switch(opcode[opcode_index]){ case 1: flag[flag_index] = tmp; ++opcode_index; ++flag_index; ++re_index; break; case 2: tmp = (char) (re[re_index] - (char)(opcode[opcode_index + 1]& 0xff)); opcode_index += 2; break; case 3: tmp = (char) (re[re_index] + (opcode[opcode_index + 1]& 0xff )); opcode_index += 2; break; case 4: tmp = (char) ((opcode[opcode_index + 1] & 0xff) ^ re[re_index]); opcode_index += 2; break; case 5: tmp = (char) (re[re_index] / (opcode[opcode_index + 1] & 0xff)); opcode_index += 2; break; case 6: ++opcode_index; break; case 8: re[tmp_index] = tmp; ++opcode_index; ++tmp_index; break; case 11: tmp = (char) (re[re_index] + 1); ++opcode_index; break; case 12: tmp = (char) (re[re_index] - 1); ++opcode_index; break; default: continue;
}
} System.out.println(new String(flag)); //757515121f3d478 }}






- End -





看雪ID:Craft_A

https://bbs.pediy.com/user-834792.htm


*本文由看雪论坛  Craft_A  原创,转载请注明来自看雪社区。



推荐文章++++

*  新手向总结:IDA动态调试So的一些坑

*  .NET 恶意代码分析入门

*  java函数转Native化的一些实践

*  2020网鼎杯玄武组_babyvm

*  中毒应急处置流程1.0









公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存